/*
 * @Author: wjc
 * @Date: 2025-09-18 15:51:17
 * @LastEditors: wjc
 * @LastEditTime: 2025-10-31 15:22:29
 * @Description: 用户信息相关
 */
import type { Recordable, ThemeModeType } from '@nice/types'

import { api, Http } from '#/api'
import { resetAllStores } from '#/stores'
import { getToken as getTokenCache, removeToken } from '#/utils/auth'
import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@nice/utils'
import { ElNotification } from 'element-plus'
import { acceptHMRUpdate, defineStore } from 'pinia'

import { useAccessStore } from './access-store'

interface BasicUserInfo {
  [key: string]: any
  /**
   * 头像
   */
  avatar: string
  /**
   * 用户id
   */
  id: string
  /**
   * 用户昵称
   */
  real_name: string
}

interface UserPreferences {
  [key: string]: any
  /**
   * 应用配置
   */
  app: {
    /** 是否移动端 */
    isMobile: boolean
    /** 布局方式 */
    layout: string
  }
  /**
   * 头部配置
   */
  header: {
    /** 顶栏是否隐藏,css-隐藏 */
    hidden: boolean
  }
  navigation: {
    /**
     * 侧边栏手风琴模式
     * @default true
     */
    accordion: boolean
  }
  shortcutKeys: {
    /** 是否启用快捷键 */
    enable: boolean
  }
  /**
   * 侧边栏配置
   */
  sidebar: {
    /** 点击目录时自动激活子菜单   */
    autoActivateChild: boolean
    /**
     * 侧边栏是否折叠
     * @default false
     */
    collapsed?: boolean
    /**
     * 侧边栏折叠时是否展示标题
     * @default false
     */
    collapsedShowTitle: boolean
    /**
     * 折叠时的宽度
     * @default 60
     */
    collapseWidth: number
    /**
     * 侧边栏是否可见
     * @default true
     */
    enable: boolean
    /**
     * 菜单自动展开状态
     * @default false
     */
    expandOnHover: boolean
    /**
     * 菜单是否折叠
     * @default false
     */
    extraCollapse: boolean
    /**
     * 侧边栏是否隐藏 - css 实现
     * @default false
     */
    hidden: boolean
    /**
     * 侧边栏混合宽度，移动端下使用
     * @default 80
     */
    mixedWidth: number
    /** 侧边栏是否展示最大化按钮
     * @default true
     */
    showMaximize: boolean
    /**
     * 侧边栏宽度
     * @default 224
     */
    width: number
  }
  theme: {
    mode: ThemeModeType
  }
  widget: {
    /** 是否锁屏 */
    lockScreen: boolean
  }
}

interface UserState {
  /**
   * 用户权限
   */
  actions?: string[]
  /**
   * 登录loading
   */
  loginLoading: boolean
  /**
   * y用户偏好设置
   */
  preferences: UserPreferences
  /**
   * 用户token
   */
  token?: string
  /**
   * 用户信息
   */
  userInfo: BasicUserInfo | null
}

/**
 * @zh_CN 用户信息相关
 */
export const useUserStore = defineStore('user', {
  state: (): UserState => ({
    userInfo: {
      id: '',
      avatar: '',
      real_name: '',
    },
    token: undefined,
    actions: [],
    loginLoading: false,
    preferences: {
      app: {
        layout: '',
        isMobile: false,
      },
      widget: {
        lockScreen: false,
      },
      shortcutKeys: {
        enable: true,
      },
      theme: {
        mode: 'light',
      },
      navigation: {
        accordion: true,
      },
      header: {
        hidden: false,
      },
      sidebar: {
        showMaximize: true,
        hidden: false,
        enable: true,
        collapsedShowTitle: false,
        collapsed: false,
        expandOnHover: false,
        collapseWidth: 60,
        width: 224,
        mixedWidth: 80,
        autoActivateChild: false,
        extraCollapse: false,
      },
    },
  }),
  persist: {
    // 持久化
    pick: ['userInfo', 'token', 'preferences', 'actions'],
  },
  getters: {
    getToken(state): string {
      return state.token || getTokenCache()
    },
    /**
     * 是否全屏显示content，不需要侧边、底部、顶部、tab区域
     */
    isFullContent(): boolean {
      return this.preferences.app.layout === 'full-content'
    },
    /**
     * 是否移动端
     */
    isMobile(): boolean {
      return this.preferences.app.isMobile
    },
    isHeaderHidden(): boolean {
      return this.preferences.header.hidden
    },
    isSidebarHidden(): boolean {
      return this.preferences.sidebar.hidden
    },
  },
  actions: {
    login(params: Recordable<any>) {
      const accessStore = useAccessStore()

      return new Promise((resolve, reject) => {
        Http.Post<
          ResponseData<{
            data: {
              token: string
              user: BasicUserInfo
            }
          }>
        >(api.login, params)
          .then((res) => {
            if (res && res.data) {
              this.userInfo = res.data.user
              this.token = res.data.token

              // 将 token 存储到 accessStore 中
              accessStore.setAccessToken(res.data.token)
              this.$router.push(DEFAULT_HOME_PATH)

              if (this.userInfo?.real_name) {
                ElNotification({
                  message: `欢迎回来:${this.userInfo?.real_name}`,
                  title: '登录成功',
                  type: 'success',
                  duration: 3000,
                })
              }
              resolve(res.data.token)
            } else {
              reject(res)
            }
          })
          .catch((error) => {
            reject(error)
          })
          .finally(() => {
            this.loginLoading = false
          })
      })
    },
    async logout(redirect: boolean = true) {
      await Http.Post(api.logout)
      removeToken() // must remove  token  first
      resetAllStores()
      this.$reset()
      // 回登录页带上当前路由地址
      await this.$router.replace({
        path: LOGIN_PATH,
        query: redirect
          ? {
              redirect: encodeURIComponent(this.$router.currentRoute.value.fullPath),
            }
          : {},
      })
    },
    getInfo(): Promise<string[]> {
      return new Promise((resolve, reject) => {
        Http.Get<ResponseData<{ data: { actions: string[]; user: BasicUserInfo } }>>(api.Me.info)
          .then((res) => {
            if (!res) {
              return reject(new Error('Verification failed, please Login again.'))
            }
            const { user, actions } = res.data
            // roles must be a non-empty array
            if (!actions || actions.length <= 0) {
              return reject(new Error('getInfo: actions must be a non-null array!'))
            }
            this.userInfo = user
            this.actions = actions
            resolve(actions)
          })
          .catch((error) => {
            reject(error)
          })
      })
    },
    changePassword() {
      return new Promise((resolve) => {
        this.logout().then(() => {
          resolve(true)
        })
      })
    },
  },
})

// 解决热更新问题
const hot = import.meta.hot
if (hot) {
  hot.accept(acceptHMRUpdate(useUserStore, hot))
}
